# coding: utf-8

import struct, logging, sys, datetime, sys
RECORD_SIZE = 82 #80  data columns + record identification + 1 string end 

log_file = 'zvm_diskacnt_parser.log'
logging.basicConfig(level=logging.DEBUG, filename=log_file, 
            format='%(asctime)s %(levelname)s: %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S')

def discant_decode (input):
	# проверить
	if (len(input)%RECORD_SIZE != 0):
		logging.error("Incorrect file size = %d" %len(input))
		#заменить на генерацию исключения
		return (None, 0)
	record_number = len(input)/RECORD_SIZE
	result = []
	for offset in range(0, record_number):
		account_dict = {}
		account_dict['User ID'] = input[offset * RECORD_SIZE : offset*RECORD_SIZE + 8].strip()
		account_dict['Account number'] = input[offset * RECORD_SIZE+ 8 : offset*RECORD_SIZE + 16].strip()
		# обработатть и привести к временному формату при необходимости, формат - mmddyyhhmmss
		account_dict['DateTime'] = input[offset * RECORD_SIZE+ 16 : offset*RECORD_SIZE + 28]
		param_names = ("Number of seconds connected to CP", "Milliseconds of processor time used", "Milliseconds of virtual CPU time used", \
								  "Number of page reads", "Number of page writes", "Number of requested virtual I/O starts for non-spooled I/O", \
								  "Number of virtual punch cards sent to a virtual punch", "Number of virtual print lines sent to a virtual printer", \
								  "Number of virtual punch cards received from a virtual reader")
		param_values = struct.unpack("9I", input[offset * RECORD_SIZE + 28 : offset*RECORD_SIZE + 64])
		account_dict.update (dict(zip(param_names, param_values)))
		account_dict['Reserved'] = struct.unpack('Q', input[offset * RECORD_SIZE + 64 : offset*RECORD_SIZE + 72])[0]
		account_dict['Number of completed virtual I/O starts for non-spooled I/O'] = struct.unpack( 'I', input[offset * RECORD_SIZE + 72 : offset*RECORD_SIZE + 76])[0]
		account_dict['CPU address'] = struct.unpack( 'H', input[offset * RECORD_SIZE + 76 : offset*RECORD_SIZE + 78])[0]
		account_dict['Card generator field'] = struct.unpack( 'B', input[offset * RECORD_SIZE + 78 : offset*RECORD_SIZE + 79])[0]
		account_dict['Accounting record identification code'] = struct.unpack( 'B', input[offset * RECORD_SIZE + 79 : offset*RECORD_SIZE + 80])[0]
		result.append(account_dict)
	return (result, record_number)

def main():
	current_date_string = datetime.datetime.today().strftime('%m%d%y')
	last_record_file_name = "last_record_" + current_date_string + r".txt"
	try:
		last_record_file = open(last_record_file_name)
	except IOError:
		last_record_index = 0
	else:
		last_record_index = int(last_record_file.read())
		last_record_file.close()
	input_file_name = r'ACCOUNT.$A' + current_date_string
	try:
		account_file = open(input_file_name, 'rb')
		account_file.seek(last_record_index * RECORD_SIZE)
		account_data = account_file.read()
		(output_data, record_number) = discant_decode(account_data)
		output_file_name = input_file_name + r".OUT" + r".txt"
		output_file = open(output_file_name, 'a')
		if output_data:
			for account in output_data:
				output_file.write ("%(User ID)s\t%(Account number)s\t%(DateTime)s\t%(Number of seconds connected to CP)d\t%(Milliseconds of processor time used)d\t"\
					 "%(Milliseconds of virtual CPU time used)d\t%(Number of page reads)d\t%(Number of page writes)d\t%(Number of requested virtual I/O starts for non-spooled I/O)d\t"\
					 "%(Number of virtual punch cards sent to a virtual punch)d\t%(Number of virtual print lines sent to a virtual printer)d\t"\
					 "%(Number of virtual punch cards received from a virtual reader)d\t%(Number of completed virtual I/O starts for non-spooled I/O)d\t"\
					 "%(CPU address)s\t%(Card generator field)s\t%(Accounting record identification code)s\n"  %account)
			status = "Add %d new records" % len(output_data)
		else: 	
			logging.debug("No new data in file %s" %input_file_name)
			status = "No new data"
		account_file.close()
		output_file.close()
	except IOError:
		logging.error('Exception:%s' %(str(sys.exc_info()[:2])))
		record_number = 0
		status = "IO error"
	last_record_file = open(last_record_file_name, 'w')
	last_record_file.write("%d"%(last_record_index + record_number))
	last_record_file.close()
	#удаление старых файлов написать
	return status

if __name__=='__main__':
	print main()	